perm filename MEMO63.PUB[HAL,HE] blob sn#117124 filedate 1974-08-28 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00008 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	.ctc: NEWSS COMPILE-TIME CONSTRUCTS
C00005 00003	Also, it is frequently useful to be able  to specify various sorts of
C00009 00004	.NEWSSS CONDITIONAL EXPANSION
C00013 00005	.NEWSSS	THE COMPILE-TIME CHECK STATEMENT
C00021 00006	.NEWSSS COMPILE-TIME PREDICATE FUNCTIONS
C00023 00007	.ctv: NEWSSS COMPILE-TIME VARIABLES
C00035 00008	.lib:NEWSS LIBRARY ROUTINES
C00047 ENDMK
C⊗;
.ctc: NEWSS COMPILE-TIME CONSTRUCTS
.asr: NEWSSS ASSERTIONS

Although the compiler makes  an effort to keep track  of the expected
runtime  state of  variables,   it sometimes  must be  given explicit
information about what values a  variable might have.  For  instance,
it is  difficult for  the compiler  to maintain  unambiguous planning
values within the THEN and the ELSE parts of conditionals. Therefore,
during each branch,  a separate "world" is in  effect,  stemming from
the world in  force before the IF.  All  variables modified in either
branch  have  planning  value  "undefined"   at  the  close  of   the
conditional. Although eventually the compiler may get smart enough to
resolve  a number of such  cases, assertions must be  used ( at least
for now) to inform the compiler of any planning values it  might need
thereafter.  For example:
.UNFILL
	IF G=1 THEN
		BEGIN
		ATTACH FROB TO YELLOW;
		MOVE FROB TO HOLE;
		OPERATE YFINGERS WITH OPENING=5;
		DETACH FROB FROM YELLOW;
		MOVE YELLOW TO YPARK;
		END;

	ASSERT YELLOW=YPARK; 
.REFILL
The ASSERT statement
tells the compiler to  use YPARK as the planning value  for YELLOW at
the  close  of  the conditional.    In  general,   information  about
variable values may be specified by statements of the form:
.UNFILL
	ASSERT <expression> <relation> <constant>
.REFILL
The <relation> must be "=", except where <expression> and <constant> are
scalars, in which case "<",">","≤", and
"%7≥%*"  may also be used.  At present, <expression> is  restricted to be
either a  variable  name  or  a linear  form  involving  only  scalar
variables.  For instance
.UNFILL
	ASSERT V = (1 2 3);
	ASSERT F1 = α#(T1) * α#(F2); 
.COMT 12
	α{Recall that T1 is not a constant, but α#(T1) --
		        ie the current planning value of T1) is. α}
.END
	ASSERT 3*S1 + 4*S2 ≤ 3;
.REFILL

Also, it is frequently useful to be able  to specify various sorts of
symbolic  information   which  can  be  used  to  direct  conditional
expansion of  various compile-time  conditionals and  by the  various
high  level primitives  (such as  INSERT  or GRASP)  provided by  the
expander. This facility is provided by the construct:
.UNFILL
	ASSERT FACT (<pattern>)
.REFILL
where <pattern> may by any sequence of identifiers and constants. For
instance:
.UNFILL
	ASSERT FACT (MACHINE TURING);
	ASSERT FACT (PAINTED ROSES RED WITH BRUSH);
	ASSERT FACT (WEIGHT ENGINE_BLOCK 4.5 POUNDS);
	ASSERT FACT (PART1 FITS_ONTO PART2 [(1,2,3):(π,0,π/2)]);
.REFILL
The actual meaning of an asserted pattern is  generally determined by
whatever conventions the user may  wish to establish.  However, a few
pattern types, such as those for attachment or those used by the very
high level  routines for  object descriptions,  are "understood"  and
used  by the  compiler.   The  user can  cause serious  confusions by
improper  introduction  or  deletion  of  such  patterns.  Generally,
assertions will  remain "true"  in the  compiler's world  model until
explicitly  deleted  or,  in  the  case  of  assertions  used by  the
compiler,  as  a  side  effect  of  processing  some  statement.  Any
assertion (whether of  a fact or of a relation)  may be undone by use
of the DENY construct, which is similar to ASSERT, except for the use
of the word "DENY".  Thus, we might have
.UNFILL
	DENY V = α#(V);
	DENY 4*X-5*Y = 10;
	DENY FACT (IN HAND SCREWDRIVER);
.REFILL
Note the  use of α#(V)  in the first  example to retrieve  the current
planning  value for  V.  After  the denial  is processed,   α#(V) will
become undefined.

Assertions may be  named by inclusion  of a  "label" field after  the
word "ASSERT", as in
.UNFILL
	ASSERT "FOO" X = 3.14;
	ASSERT "BAZ" 4*X-10*Y %7≥%* 1;
	ASSERT "FOOBAZ" FACT(IN HAND HAMMER);
.REFILL
This  construct is  very  useful for  deleting  an assertion  without
having to recall it exactly.  For instance,
.UNFILL
	DENY "BAZ";
.REFILL
would have the same effect as
.UNFILL
	DENY 4*X-10*Y %7≥%* 1;
.REFILL

NOTE: A possible source of confusion is  the fact that assertions are
purely  a compile-time construct used  to direct compilation.   It is
not possible to view the assertional structure at runtime.
.NEWSSS CONDITIONAL EXPANSION

It is frequently desirable to write a  fairly general piece of source
code that produces  different object code,  depending on the specific
task to  be performed and  on the  compiler's model  of the  expected
runtime  environment.   The  principal  mechanism  provided for  this
purpose is the compile-time conditional construct, which behaves like
a conventional Algol  "IF",   except that it  is resolved at  compile
time,   with only the  the "expanded" part  having any effect  on the
compiler's world model.  The syntax is:
.UNFILL
	COMPILE IF <condition> THEN
		<then-part>
	ELSE
		<else-part>
.REFILL
where the "ELSE" component may be omitted  if desired.  The condition
may  be  any  boolean  expression  involving  only  constants.    For
instance:
.UNFILL
	COMPILE IF α#(BLUE)%7≠%*BPARK THEN
		MOVE BLUE TO BPARK;
.REFILL
Also, the results  of symbolic assertions  may be tested by  means of
the FACT construct, as in
.UNFILL
	COMPILE IF FACT (IN TOOLRACK SCREWDRIVER) THEN
		BEGIN
.COMT 20
		α{ Code to fetch the screwdriver out
		        of the tool rackα}
.END
		END;
.REFILL
When used in  this way, FACT  expressions are boolean  primaries, and
can enter into more complicated boolean expressions in the usual way.
For instance:
.UNFILL
	COMPILE IF FACT(GOES_IN SHAFT1 HOLE1)
			∧%7¬%*FACT(IN SHAFT1 HOLE1) THEN
		BEGIN
		COMPILE IF FACT(THREADED SHAFT1) THEN
			BEGIN
.COMT 28
			α{ here code to insert a threaded screwα}
.END
			ASSERT FACT (SCREWED SHAFT1);
			END
		ELSE
			BEGIN
.COMT 28
			α{ here code to insert a smooth pinα}
.END
			ASSERT FACT (SLIPPED_IN SHAFT1);
			END;
		ASSERT FACT (IN SHAFT1 HOLE1);
		END;
.REFILL
Frequently, one may want  to test a whole class of  asserted facts at
once. For  instance, suppose we may want to know  if the blue hand is
available for some task or another.  We can keep track of what  is in
the hand by means of assertions like
.UNFILL
	ASSERT FACT (BLUE HOLDS WIDGET);
.REFILL
However, it  is frequently inconvenient,   and  sometimes impossible,
explicitly to test all possibilities, as in:
.UNFILL
	COMPILE IF %7¬%*FACT(BLUE HOLDS WIDGET) 
		∧ %7¬%*FACT(BLUE HOLDS FROB) ∧ . . . THEN
			BEGIN
			comment whatever;
			END;
.REFILL

The reserved word ANYTHING  is provided as a wild card  to avoid this
difficulty.  Thus, we can write:
.UNFILL
	COMPILE IF %7¬%*FACT(BLUE HOLDS ANYTHING) THEN
		BEGIN
		comment whatever;
		END;
.REFILL

.NEWSSS	THE COMPILE-TIME CHECK STATEMENT

	Since library routines will be commonly used, it is necessary
to have some  way of checking that necessary preconditions are met as
the first steps of the library routine.  The way this is done is with
the CHECK statement.  A simple example:
.unfill
	CHECK  X=3 ∧  Y>5
.refill
   The  contents of  the check  may be  any
boolean expression,  including checks on the current world model. The
check is only  made at compile-time; if  the check is not  satisfied,
the compiler will generate an error message.
The effect of this statement is exactly like that of
.UNFILL
	COMPILE IF %7¬%*(X=3 ∧ Y>5) THEN 
		COMPILE_ERROR("CHECK STATEMENT FAILED")   .
.REFILL

.NEWSSS BINDING BOOLEANS

Frequently the construct ANYTHING does not suffice.   For example,
the  user may want  to execute different  code, depending  on what is
supposed to be in the  blue hand.  Compile-time variables, which  are
described more fully  in {sssref ctv}, provide a means  of doing this.
Such  variables have no runtime existence  whatsoever.  Instead,  the
compiler can  set their  "planning" value to  the internal  structure
associated with  any string of valid  tokens in the  language.  Then,
whenever the parser encounters the "α#(vi)" for compile time  variable
vi,  it substitutes  the associated "value".  For  instance,  suppose
the  compile time variable "HAND_ID"  has been given  (by some means)
the value "YELLOW". Then 
.UNFILL
	MOVE α#(HAND_ID) TO FOO;
.REFILL
is identical to
.UNFILL
	MOVE YELLOW TO FOO;
.REFILL
There are a  number of  ways (discussed  in {sssref ctv})  by which  a
compile-time  variable may  given  a  value.   One  of  these is  the
construct
.UNFILL
	BIND(Vi) 
.REFILL
in  a FACT pattern  within a  boolean test.   BIND(Vi) acts something
like  ANYTHING in  that  it  will  match any  token  occurring  at  a
corresponding  place in a  pattern.   However, it has  the additional
effect of  setting the  planning  value of  Vi to  the  corresponding
element in the matched pattern.  For instance,
.UNFILL
	COMPILE_TIME THING,WHERE;
	:
	ASSERT FACT (BLUE HOLDS FROB);
	ASSERT FACT (CORRECT_SPOT_FOR FROB [(1,2,3):(π,0,0)]);
	ASSERT FACT (CORRECT_SPOT_FOR WIDGET [(4,5,6):(π,0,0)]);
	:
	COMPILE IF FACT(BLUE HOLDS BIND(THING)) THEN
		BEGIN
		IF FACT (CORRECT_SPOT_FOR α#(THING) BIND(WHERE)) THEN
			BEGIN
			MOVE BLUE TO α#(WHERE);
			comment ... etc ... ;
			END
		ELSE
			BEGIN
			comment some sort of error message, perhaps;
			END;
		END;
.REFILL
Would expand into
.UNFILL
	MOVE BLUE TO [(1,2,3):(π,0,0)];
	comment ... etc ...;
.REFILL

.NEWSSS COMPILE FOREACH

Sometimes, there may be several assertions in the data base that could
satisfy a given FACT retrieval pattern.  For instance,
.UNFILL
	ASSERT FACT(S1 SCREWS INTO H1);
	ASSERT FACT(S2 SCREWS INTO H2);
	ASSERT FACT(S3 SCREWS INTO H3);

	:

	COMPILE IF FACT(BIND(S) SCREWS INTO BIND(H)) THEN
		BEGIN
		:
		END
.REFILL
In  such cases,  the  compiler  would  arbitrarily pick  one  of  the
eligible  patterns  to  use  as  its  "template" for  performing  any
requested bindings.  Suppose, however, that the user wants to perform
some action for each pattern that matches, rather than  for only one.
For  instance, she  may want  to  insert all  the  screws  into their
corresponding holes.  The compile-time FOREACH construct is intended
to allow this sort of thing.
.UNFILL
	COMPILE FOREACH <condition> DO
		 <statement>
.REFILL
where the <condition> must have the form
.UNFILL
	FACT (<pattern>)
.REFILL
This construct will cause <statement> to be compiled once for each 
instance of <pattern> that finds a match in the data base.

For instance, a library routine that fastens down a head to an engine
block 
by means of bolts which can be inserted in any order
might include a sequence like:
.UNFILL
	COMPILE_TIME BOLT,HOLE_ID,HEAD_ID;
	:
	COMPILE FOREACH FACT( BIND(BOLT) FASTENS α#(HEAD_ID)) DO
		BEGIN
		COMPILE IF FACT(α#(BOLT) FITS INTO BIND(HOLE_ID)) THEN
			INSERT α#(BOLT) INTO α#(HOLE_ID)
		ELSE
			BEGIN
			COMMENT an error message;
			END;
		END;
.REFILL
If we then have assertions:
.UNFILL
	ASSERT FACT (B1 FASTENS PUMPHEAD);
	ASSERT FACT (B2 FASTENS PUMPHEAD);
	ASSERT FACT (B3 FASTENS PUMPHEAD);
	ASSERT FACT (B1 FITS INTO H1);
	ASSERT FACT (B2 FITS INTO H2);
	ASSERT FACT (B3 FITS INTO H3);
.REFILL
and call our library  routine to put on PUMPHEAD,  the above fragment
would expand into 
.UNFILL
	:
	INSERT B1 INTO H1;
	INSERT B2 INTO H2;
	INSERT B3 INTO H3;
	:
.REFILL

.NEWSSS COMPILE-TIME PREDICATE FUNCTIONS

HAL provides several useful predicate functions that are evaluated
at compile-time.  One of these is 
.UNFILL
	SPECIFIED(<routine parameter>)
.REFILL
which may be used inside a routine to tell whether some parameter has been
specified in the call to the routine.  (See {ssref lib}).  Another is
.UNFILL
	HAS_VALUE(<variable>)
.REFILL
which tells whether the <variable> currently has a planning value.  For instance,
.UNFILL
	SCALAR X,Y,Z;
	COMPILE IF %7¬%*HAS_VALUE(X) THEN
		BEGIN
		ASSERT X=3;
		Yα←X;
		END;
	:
	COMPILE IF HAS_VALUE(X) THEN
		Zα←α#(X)
	ELSE
		Zα←5;
.REFILL
would expand into
.UNFILL
	SCALAR X,Y,Z;
	ASSERT X=3;
	Yα←X;
	Zα←3;
.REFILL
if X has no planning value.

.ctv: NEWSSS COMPILE-TIME VARIABLES

Compile-time variables in many ways resemble macros, and may (to some
extent) be used  as such.  The principle difference (but not the only
difference) is that macros work at the text level (i.e.,  expand into
strings  of characters),  while  compile-time variables  work at  the
token  level. This provides a  number of implementation efficiencies,
as well as a nice "hook" for those parts of HAL,  such as the pattern
matcher or library routines, that manipulate compiler constructs.

Compile-time variables are declared by the construct
.UNFILL
	COMPILE_TIME v1,v2,...,vn;
.REFILL
As  mentioned earlier,  they  have no  runtime  existence whatsoever.
Instead, the compiler can set their "planning value" to be any string
of tokens in  the language.  Then,  for compile time variable  V, the
construct
.UNFILL
	α#(V)
.REFILL
produces the  same effect  as  if the  current  value of  V  had been
explicitly included in the source program.

We have already discussed one method (the BIND construct) by  which a
value may be given to a  compile-time variable.  The other common way
is the assignment statement:
.UNFILL
	<ct var> α← <ct var>
.REFILL
For instance,
.UNFILL
	COMPILE_TIME A,B;
	:
	Aα←B;
	  COMMENT this causes the planning value of A to 
		be set to the current planning value of B,
		so that, now, α#(A) is the same as α#(B) ;
	:
.REFILL
HAL also includes a  number of constructs that cause  the compiler to
invent  a  "temporary" compile-time  variable  containing  some token
string as its value.  For example, if a body of text appears in macro
delimiters  in  an "unexpected"  place, that is,    not in  a  macro
definition  or macro  parameter list,  then the  compiler scans the
enclosed text and builds a compile-time variable (with an unprintable
name) whose value is the resulting token string. Thus if we have
.UNFILL
	COMPILE_TIME A;
	:
	Aα←⊂GO DIRECTLY TO JAIL⊃;
.REFILL
then 
.UNFILL
	α#(A);
.REFILL
will yield
.UNFILL
	GO DIRECTLY TO JAIL;
.REFILL
Note also that
.UNFILL
	α#(⊂More garbage⊃)
.REFILL
merely gives 
.UNFILL
	More garbage
.REFILL
Normally, expansion  of the "planning value" construct  is turned off
while the delimited  text is  being tokenized.   This  allows you  to
store  things  like  α#(var) inside  a  compile-time  variable.    For
instance,
.UNFILL
	COMPILE_TIME FOO,BAZ;
	BAZ α← ⊂CENTER α#(FOO)⊃;
	:
	FOO α← ⊂ YFINGERS ⊃;
	α#(BAZ);
	:
	FOOα← ⊂ BFINGERS ⊃;
	α#(BAZ);
.REFILL
This expands into
.UNFILL
	CENTER YFINGERS;
	:
	CENTER BFINGERS;
.REFILL
The construct 
.UNFILL
	EXPAND(<ct variable>)
.REFILL
produces a new compile-time variable whose  value is the "evaluation"
of its argument.  The meaning of this is best shown by an example:
.UNFILL
	BAZα←⊂CENTER α#(FOO)⊃;
	FOOα←⊂YFINGERS⊃;
	BARα←EXPAND(BAZ);
.REFILL
gives the same effect as
.UNFILL
	BARα←⊂CENTER YFINGERS⊃;
.REFILL
One frequent use of  assertions is to specify a  number of properties
of some object or variable.  For instance,
.UNFILL
	ASSERT FACT(HEIGHT widget 100);
	ASSERT FACT(WEIGHT widget 200);
	ASSERT FACT(DEPROACH widget [(1,2,3)|(π,0,0)]);
.REFILL
These properties  may be retrieved by means  of a binding boolean, as
in
.UNFILL
	COMPILE IF FACT(HEIGHT widget BIND(h)) THEN
		BEGIN
		MOVE YELLOW TO widget*[(0,0,α#(h)):(0,0,0)];
		:
		END;
.REFILL
Unfortunately, binding is frequently rather inconvenient  as a means for
fetching  a  single  value, since  it  requires  explicit  use of  an
auxiliary variable.  In such  cases, the PICK construct can be  used
instead, as in
.UNFILL
	MOVE YELLOW TO f1
		USING WEIGHT=α#(PICK(WEIGHT widget BIND(*)) );
.REFILL
In general, PICK has the form
.UNFILL
	PICK(<pattern>)
.REFILL
where <pattern> is just like the FACT  patterns discussed in previous
sections, except that it contains "BIND(*)" as one term.  PICK causes
the compiler  to  create  a  new compile-time  variable  whose  value
corresponds to  the BIND(*) term  in the  matched fact from  the data
base.  If no value  is found  then a null  value is used.   Note that
<pattern> can also contain instances of ANYTHING or BIND(<variable>),
as in:
.UNFILL
	ASSERT FACT ( GADGET FITS ONTO WIDGET AT [(0,0,0):(π,0,0)]);
	:
	OBJα←PICK(GADGET FITS ONTO BIND(*) ANYTHING BIND(LOCN));
.REFILL
which would set the value of OBJ to "WIDGET" and the value of LOCN to
"[(0,0,0):(π,0,0)]".

Another occasionally  useful facility is the  ability to extract part
of a token stream.  HAL provides a number of "subfield" operations to
perform this function.  The simplest is
.UNFILL
	<ct variable>[<index>]
.REFILL
which  creates  a  new  compile-time  variable  whose  value  is  the
<index>th  element of α#(<ct  var>).  (The exact  meaning of "element"
will be  discussed  in a  moment.  For the  present, "token"  may  be
substituted.) For example:
.UNFILL
	POEM α← ⊂ ARMA VIRUMQUE  CANO, TROJAE QUI PRIMUS AB ORIS . . .⊃
	:
	Bα←POEM[3]; Comment: now α#(B) is "CANO";
.REFILL
Subsequences of elements may be obtained through use of 
.UNFILL
	<ct variable>[<index> FOR <count>]
.REFILL
and 
.UNFILL
	<ct variable>[<lower bound> TO <upper bound>]
.REFILL
which do the "obvious" thing.  For instance,
.UNFILL
	Bα← POEM[2 TO 3];  Comment sets α#(B) to "VIRUMQUE CANO";
	Cα← ⊂HIP BONE CONNECTED TO THE THIGH BONE⊃[1 FOR 2]; 
 			Comment gives "HIP BONE";
.REFILL
Suppose we want to extract the frame constant from a construct like
.UNFILL
	ASR α← ⊂ ASSERT YELLOW = [(0,1,2):(π,0,0)]⊃;
.REFILL
If the  extraction operator worked  purely on  the token level,  we'd
have  to say something like  α#(ASR[4 FOR 19]), which  somehow seems a
lot less natural than  saying "ASR[4]".  To  allow for this, the  HAL
extraction primitives treat things inside paired "nesting" characters
(⊂⊃,(),[],   and  α{α})  as  single   elements.  Also,  the  constructs
BIND(var), PICK(<pattern>), FACT(<pattern>), and  INDEX(v1,v2)  are  all
treated as single elements.  Thus
.UNFILL
	⊂ A B (C*3) D ⊃[3] 
	⊂ A + B * C [(X,Y,Z):(π,0,0)] ⊃[6]
	⊂ ASSERT FACT(HUMAN TURING) ⊃[2]
	⊂ BIND(A) PICK(HUMAN BIND(*)) ANYTHING ⊃[3]
.BULL
expand to
	(C*3)
	[(X,Y,Z):(π,0,0)]
	FACT(HUMAN TURING)
	ANYTHING
.REFILL
The same nesting rules apply to FACTs.  Thus if we have
.UNFILL
	ASSERT FACT( PROPERTIES hammer ⊂WEIGHT x LOCUS (f*y) ⊃);
	:
	hpropsα←PICK(PROPERTIES hammer BIND(*));
.BULL
then
	α#(hprops) 	 expands to 	 ⊂WEIGHT x LOCUS (f*y) ⊃
	hprops[4] 	expands to 	(f*y)
.REFILL
Note that here α#(hprops) still  includes the "⊂ ⊃" and will hence yield
a new compile-time variable.

Another occasionally useful facility is the ability to determine  the
index  of an  element  in  a string  of  tokens.   This  function  is
performed by the INDEX primitive:

	INDEX(<ct var 1>,<ct var 2>)

which  produces an integer constant  whose value is the  index of the
first occurrence of α#(<ct var 1>) in α#(<ct var 2>).  This function is
especially  useful  in  extracting  properties  from  a  list.    For
instance:
.UNFILL
	PROPLα←⊂WEIGHT 1 HEIGHT 200 LOCATION [(1,2,4):(π,0,0)]⊃;
		Comment INDEX(⊂HEIGHT⊃,PROPL) = 3 ;
	Wα←PROPL[1+INDEX(⊂WEIGHT⊃,PROPL)]; Comment Now α#(W)=1;
.REFILL

.lib:NEWSS LIBRARY ROUTINES

Many of the  applications for which HAL is  intended characteristicly
involve repeating  a number of very similar  subtasks.  For instance,
an assembly  program might  have  to change  sockets on  an  electric
driver many times in order to drive down a number of different bolts.
If  written in  "simple"  HAL, with  each such  subtask coded  out in
explicit statements like MOVE and   OPERATE, such  programs would be
very tedious to write and debug.  On the other hand, the necessity of
planning motions  frequently  makes procedures  (in  the  traditional
sense) infeasible.   To  overcome this  difficulty,   HAL provides  a
facility for  "routines", which externally resemble  macros,  in that
they are "expanded" each  time they are  invoked,  although they  are
are  stored  and manipulated  by  the  compiler  in a  somewhat  more
efficient  manner.  The HAL system  will include a predefined library
of routines  for performing  a number of  commonly useful  functions,
although a user can, of  course,  "roll her own" by using the ROUTINE
construct, which has the form
.UNFILL
	ROUTINE <id> (<parameter list>);
		<body>
.REFILL
where  the <parameter  list>  syntax is  the  same as  for  procedure
definitions,    and the  <body>  may  be either  an  expression  or a
statement. When the library routine is expanded, all instances of the
parameter names  are substituted with the  actual parameters supplied
in the  call.  Thus, a typical library routine declaration might look
like:
.UNFILL
	ROUTINE reach(SCALAR thickness;FRAME place);
		BEGIN
.COMT 20
		COMMENT causes the hand to move to the indicated
			spot, and keep opening & closing its fingers
			until something is put in them;
.END
		SCALAR flag;
		MOVE YELLOW TO place;
		flagα←1;
		WHILE flag%7≠%*0 DO
			BEGIN
			OPERATE YFINGERS WITH OPENING = 5;
			OPERATE YFINGERS WITH OPENING = thickness-.1
				ON YTOUCH DO
					BEGIN
					flagα←0;
					STOP;
					END;
			END;
		END
.REFILL


Library routines without  parameters are invoked simply  by including
their  name in the source  program.  For instance,  suppose we have a
library routine PARK_YELLOW which parks the yellow arm.  Then
.UNFILL
	IF h>3 THEN 
		PARK_YELLOW
.REFILL
might expand into something like
.UNFILL
	IF h>3 THEN
		MOVE YELLOW TO YPARK
.REFILL
There  are several  ways  to specify  parameters.   Perhaps  the
simplest is  to follow the syntax for  procedure calls, in which case
the arguments must  correspond in order  and type  with those in  the
statement which defined the routine.  For example, 
.UNFILL
	reach(0.5, [(1,2,3):(π/2,π/2,0)])
.REFILL
This can  become very inconvenient  for routines  which have a  large
number of parameters, since the user may have trouble remembering the
correct  order,  or  may  want  to  leave  some   unspecified.  These
difficulties are avoided by using the form
.UNFILL
	reach(thickness = 0.5,  place = [(1,2,3):(π/2,π/2,0)])
.REFILL
It is possible to specify default values for parameters to library 
routines by including the construct
.UNFILL
	(DEFAULT <value>)
.REFILL
after the parameter name in the formal parameter list for the routine.
For example,
.UNFILL
	ROUTINE reach(FRAME arm(DEFAULT YELLOW),place;
				    SCALAR thickness(DEFAULT 0));
		BEGIN
		:
		END

	:
	reach(BLUE,f1);  comment a thickness of 0 is assumed;
	reach(place=f2,thickness=10); comment YELLOW arm assumed;
.REFILL

The construct
.UNFILL
	SPECIFIED(<parameter id>)
.REFILL
may be used in a compile-time conditional to test whether the named
parameter has been assigned a value.  For example, 
.UNFILL
	ROUTINE transmogrify(COMPILE_TIME errdev;...);
		BEGIN
.COMT 20
		COMMENT Note here that the compile-time variable
			errdev is merely being used as a name
			passing mechanism.  I.e., we aren't
			saying α#(errdev) anywhere. ;
.END
		:
		IF errcond THEN
			BEGIN
			COMPILE IF SPECIFIED(errdev) THEN
				OPERATE errdev
			ELSE
				ABORT;
			END;
		:
		END;
.REFILL
If a parameter has no default value specified and is not bound by the
call, then any expansion of the routine that uses the parameter will
result in an error; occurrences of an unbound parameter in the unexpanded
part of a compile time conditional are legal.  

Yet another syntax is acceptable for  invocation of library routines;
it  is included  for compatibility  with  high level  primitives (see
{secref vhl}).  In this form, the parameter names act like key words
identifying various clauses in a "pseudo-english" statement, as in
.UNFILL
	REACH thickness 0.5 place [(1,2,3):(π/2,π/2,0)];
.REFILL
If a  parameter to a  routine occurs  in the  body in some  construct
where a variable  must occur (eg. the left hand  side of an assignment
statement),  the  compiler  will  do  the  "right"  thing  when   the
corresponding actual parameter is a constant or  expression: a
warning  will be printed,  and the  compiler will invent  a temporary
variable to hold the value.
.NEWSSS SAVING LIBRARY ROUTINES

Library routines may be saved on a file by  use of the statement (and
supervisor command)
.UNFILL
	SAVE <flag> <routine name list> ON <file specifier>
.REFILL
where <flag> may be either NEW, OLD, or <empty>. For instance,
.UNFILL
	SAVE reach, transmogrify ON "FEE.FIE[FO,FUM]";
	SAVE OLD foobaz ON "DEFS.1[II,HE]";
	SAVE NEW grab1, grab2, grab3 ON "GRABS";
.REFILL
IF <flag> is  <empty> and one of the named routines already exists on
the specified file, the old  definition is overwritten. IF <flag>  is
NEW, then only  routines which do not already exist  on the specified
file  will be added.  Similarly, if  <flag> is OLD then only routines
which are already on  the file will be  saved.  If the  <routine name
list> is  omitted, then  all existing routines  will be saved  on the
specified file.  E.g.
.UNFILL
	SAVE ON "DEFS.ALL";
	SAVE NEW ON "DEFS.2";
.REFILL
Library routines may be retrieved from a file by the command
.UNFILL
	RETRIEVE <flag> <routine name list> FROM <file specifier>
.REFILL
If <flag> is  empty, then  the specified routines  will be  retrieved
from the  specified file.   If, however,   <flag>  is NEW, then  only
routines which are  not already defined will be read in; if <flag> is
OLD, then only routines which  are already defined will be  retrieved
(they will  be redefined).   If the  <routine name list>  is <empty>,
then  all  routines  on  the  file  will  be  read  (subject  to  any
restrictions imposed by <flag>).  Examples:
.UNFILL
	RETRIEVE FROM "DEFS.RCB";
	RETRIEVE Aeneas, Dido FROM "CAVE";
	RETRIEVE NEW FROM "HAL.LIB[HAL,HE]";
.REFILL

.NEWSSS	SAVING AND RESTORING PLANNING VALUES

	The statement SAVE WORLD  ON W1 will  cause the "world"  at
that  point in  the planning  to be  written out  into a  file called
W1.WLD.   The statement RETRIEVE WORLD FROM  W1 will read in this file
and set  up the world  as it was  when saved.
The world includes all planning values and all assertions.  It does
not include defined library routines.
Saving the world is  particularly
useful for  recovering when  the arm runs  into trouble; it  makes it
unnecessary to begin the planning from scratch.

  It is also  possible
to improve the planning values of frames after a period of execution;
this is done by the statement RESTORE WORLD FROM RUNTIME.
The effect of this is that all the variables which the runtime knows
about are read, and their values become the new planning values
for those variables.